import os

from osc_base import OSCBaseObject

import jsonhandler
import widgets

class iOSCController(OSCBaseObject):
    def __init__(self, **kwargs):
        self.MainController = kwargs.get('MainController')
        self.comm = self.MainController.comm
        kwargs.setdefault('osc_parent_node', self.MainController.osc_parent_node)
        kwargs.setdefault('osc_address', 'iOSCControl')
        super(iOSCController, self).__init__(**kwargs)
        self.widgets = {}
        self.clients = {}
        
        self.comm.connect('state_changed', self.on_comm_state)
        self.MainController.DeviceSystem.connect('new_device', self.on_ds_new_device)
        self.comm.osc_io.connect('new_master', self.on_osc_new_master)
        self.comm.osc_io.connect('client_added', self.on_osc_client_added)
        self.comm.osc_io.connect('client_removed', self.on_osc_client_removed)
        
        self.build_test_stuff()
        
    def add_widget(self, clsname, **kwargs):
        cls = widgets.widget_classes.get(clsname)
        if cls:
            w_kwargs = kwargs.copy()
            w_kwargs.update({'osc_parent_node':self.osc_node, 
                             'osc_root_address':self.osc_address, 
                             'osc_client_address':'DWT-iPad'})
            w = cls(**w_kwargs)
            self.widgets.update({w.id:w})
            return w
            
    def build_test_stuff(self):
        #btn = self.add_widget('Toggle', name='testbtn', label='testbtn', width=.1, height=.1)
        #btn.connect('state_changed', self.on_test_btn_cb)
        #slider = self.add_widget('VSlider', name='testslider', x=.7, y=0, width=.08, height=.4)
        #slider.connect('value_update', self.on_test_slider_update)
        #self.add_widget('Label', name='testlabel', x=0, y=.5, value='test')
        for x in range(4):
            slider = self.add_widget('VSlider', name='testslider_'+str(x+1), 
                                     x=x*.1, y=0, width=.08, height=.4, 
                                     min=0, max=255, foregroundColor=[0, 255, 0], 
                                     backgroundColor=[128, 128, 128, 255])
                                     
            slider.connect('value_update', self.on_test_slider_update)
            
        self.add_widget('xyPad', name='testxy', x=.1, y=.5, width=.2, height=.2, max=255, 
                        src_object=self.MainController.Selection.AttributeGroups['Position'], 
                        src_attr = 'value', src_signal='value_changed', scale_factor=255)
        self.add_widget('Button', name='testbtn', label='Test', y=.8)
                        #ontouchstart="destinationManager.selectIPAddressAndPort(control.destinationIP, control.destinationPort)")
            
        s = self.build_interface(client_name='DWT-iPad', interface_name='test1', orientation='landscape', destination=['192.168.1.51', '18888'])
        file = open(os.path.join(os.path.dirname(__file__), 'test_template.js'), 'w')
        file.write(s)
        file.close()
        
    def on_test_btn_cb(self, **kwargs):
        #print 'got button state:', kwargs.get('state')
        slider = self.widgets['testslider']
        v = slider.value
        slider.value = v + .1
        
    def on_test_slider_update(self, **kwargs):
        widget = kwargs.get('widget')
        value = kwargs.get('value')
        i = int(widget.name.split('_')[1])
        #print 'slider value: ', value
        #self.widgets['testlabel'].value = '%.2f' % (value)
        
#        device = self.MainController.DeviceSystem.DevicesByNum.get(i)
#        if device:
#            attrib = device.attr_by_chan.values()[0]
#            if attrib:
#                attrib.value = value
    def on_ds_new_device(self, **kwargs):
        if kwargs.get('base') == 'PatchedDevice':
            device = kwargs.get('device')
            attrib = device.attr_by_chan.values()[0]
            widget = self.widgets.get('testslider_%s' % (device.device_num))
            if widget:
                widget.set_src_object(src_object=attrib, src_attr='value', src_signal='value_changed')
        
    def build_interface(self, **kwargs):
        client_name = kwargs.get('client_name')
        template = kwargs.get('template')
        name = kwargs.get('interface_name')
        orientation = kwargs.get('orientation')
        
        if not template:
            template = jsonhandler.load_template()
        script = template['script']
        if name:
            script = jsonhandler.set_script_vars(script, loadedInterfaceName=name)
        if orientation:
            script = jsonhandler.set_script_vars(script, interfaceOrientation=orientation)
        dest = [str(self.comm.osc_io.hostdata[key]) for key in ['hostaddr', 'recvport']]
        script += 'destinationManager.selectIPAddressAndPort("%s", "%s");' % (dest[0], dest[1])
        
        template['script'] = script
        
        for w in self.widgets.itervalues():
            l = w.build_interface_dict(root_address=client_name)
            template['pages'][0].extend(l)
        return jsonhandler.build_interface(**template)
        
    def send_client_interface(self, **kwargs):
        name = kwargs.get('name')
        if name in self.clients:
            s = self.build_interface(client_name=name, orientation='landscape', interface_name='test1')
            if len(s) > 4000:
                raise MsgLengthError
            self.osc_node.get_root_node().send_message(root_address='pushInterface', address=[''], value=s, client=name)
    
    def on_comm_state(self, **kwargs):
        return
#        s = self.build_interface(client_name='DWT-iPad', orientation='landscape', interface_name='test1')
#        if len(s) > 4000:
#            raise MsgLengthError
#        self.osc_node.get_root_node().send_message(root_address='pushInterface', address=[''], value=s)
        
        
    def add_client(self, **kwargs):
        client = kwargs.get('client')
        self.clients.update({client.name:client})
        #self.clients.update({name:tuple([kwargs.get(key) for key in ['address', 'port']])})
        #if self.osc_node.oscMaster:
        #    self.send_client_interface(name=client.name)
            
    def remove_client(self, **kwargs):
        client = kwargs.get('client')
        if client.name in self.clients:
            del self.clients[client.name]
            
    def set_widget_links(self, state):
        for w in self.widgets.itervalues():
            w.set_link_state(state)
        
    def on_osc_new_master(self, **kwargs):
        ## link if master is local, unlink if not
        self.set_widget_links(self.osc_node.oscMaster)
    
    def on_osc_client_added(self, **kwargs):
        client = kwargs.get('client')
        if 'Control' in client.name:
            self.add_client(**kwargs)
            client.sendAllUpdates = True
            
    def on_osc_client_removed(self, **kwargs):
        client = kwargs.get('client')
        if 'Control' in client.name:
            self.remove_client(**kwargs)

class MsgLengthError(Exception):
    def __str__(self):
        return 'message length exceeded'
        
